/* Copyright (c) 2011 Alexandre Défossez, Timothée Lacroix
 * This file is part of HINAPT.
 *
 * HINAPT is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * HINAPT is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with HINAPT.  If not, see <http://www.gnu.org/licenses/>.
 */


#include "detector.hpp"


ofstream debugOut;

void DetectorTh::print(){
  for(int i=0;i<(int)size();i++){
    cout<<"Classifier "<<i+1<<endl;
    (*this)[i]->print();
  }
}

void DetectorTh::detect(vector<Rect> &eyes,Mat &img,double ratio,double prof){
  int height=img.size().height;
  int width=img.size().width;
  int s=min(height,width);
  double weight=double(nbTranche*nbTranche)/double(height*width);
  for(int i=0;i<prof;i++){
    for(int y=0;y+s<height;y++){
      for(int x=0;x+s<width;x++){
        Mat sImg(img,Rect(x,y,s,s));
        if(eval(sImg,weight)==1){
          cout<<"oeil detecte en "<<x<<" "<<y<<" size: "<<s;
          eyes.push_back(Rect(x,y,s,s));
        }
      }
    }
    s=double(s)*ratio;
  }

}

bool DetectorTh::load(istream &input){
  clear();
  int s;
  input>>s;
  for(int i=0;i<s;i++){
    ClassifierTh *a=new ClassifierTh;
    if(!a->load(input))
      return false;
    push_back(a);
  }
  return !(input.fail());
}

bool DetectorTh::save(ostream &output){
  output<<size()<<" ";
  for(int i=0;i<(int)size();i++)
    if(!(*this)[i]->save(output))
      return false;
  return !(output.fail());
}

int DetectorTh::eval(Mat img,double weight){
  for(int i=0;i<(int)size();i++)
    if((*this)[i]->eval(img,weight)==-1)
      return -1;
  return 1;
}

void DetectorTh::findFD(double &F,double &D,
            vector<Mat>& validationSet,
            vector<int> &trueVal){
  double nbDetected,nbF;
  double totOk,totF;
  nbDetected=nbF=totOk=totF=0;

  vector<double> evals(trueVal.size());

  #pragma omp parallel for
  for(size_t i=0; i<trueVal.size();i++){
    evals[i] = eval(validationSet[i]);
  }

  for(int i=0;i<(int)trueVal.size();i++){
    if(trueVal[i]==1)
      totOk++;
    else totF++;
    int val=evals[i];
    if(trueVal[i]==1 && val==1)
      nbDetected++;
    if(trueVal[i]==-1 && val==1)
      nbF++;
  }
  F=nbF/totF;
  D=nbDetected/totOk;
}

void DetectorTh::findD(double &D, vector<Mat>& validationSet,
                       vector<int> &trueVal){
  double nbDetected;
  double totOk;
  nbDetected=totOk=0;

  vector<double> evals(trueVal.size());

  #pragma omp parallel for
  for (size_t i=0; i<trueVal.size(); i++){
    if (trueVal[i]==1)
      evals[i] = eval(validationSet[i]);
  }

  for(int i=0;i<(int)trueVal.size();i++){
    if(trueVal[i]==1){
      int val=evals[i];
      totOk++;
      if (val==1)
        nbDetected++;
    }
  }
  D=nbDetected/totOk;
}
